package crawler;

import java.util.LinkedList;
import java.util.List;

import org.htmlparser.Node;
import org.htmlparser.Parser;
import org.htmlparser.parserapplications.StringExtractor;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.EncodingChangeException;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.ObjectFindingVisitor;

import structures.InfoPacket;
import structures.TaskType;

public class Crawler extends Thread {

	// połączenie z serwerem
	CrawlerConnection connection;

	// konstruktor z połączeniem
	public Crawler(int port, String address) {
		connection = CrawlerConnection.getConnector(port, address);
	}

	//wyszukiwanie słowa na stronie
	private boolean findWord(String currentURL,String phrase) {
		
		//tworzenie ekstraktora na podstawie url
		StringExtractor extractor = new StringExtractor(currentURL);
		
		//czy szukane słowo istnieje
		boolean returnValue = false;
		try {
			//wyszukanie słowa
			String a = extractor.extractStrings(false);
			if (a==null)
				System.out.println("Crawler: The string extractor did not find anything");
			else if(phrase == null)
				System.out.println("The search phrase is invalid.");
			else{
				a=a.toLowerCase();
				returnValue = a.contains(phrase.toLowerCase());
				}
		} catch (ParserException e) {
			e.printStackTrace();
		}
		return returnValue;
	}

	//wyszukiwanie linków na stronie
	private List<String> parseURL(String currentURL) {

		//utworzenie obiektu parsera do przeszukiwania
		Parser parser = null;
		//lista linków
		List<String> returnList=new LinkedList<String>();
		try {
			parser = new Parser(currentURL);
		} catch (ParserException e) {
			return returnList;
		}
		
		ObjectFindingVisitor visitor = new ObjectFindingVisitor(LinkTag.class);

		try {
			parser.visitAllNodesWith(visitor);
		} catch (EncodingChangeException e1) {
			try {
				//parsujemy drugi raz, według twórców powinno działać
				parser.visitAllNodesWith(visitor);
			} catch (ParserException e11) {
				
				System.out.println("Second parsing also failed ");
			}
		}catch (ParserException e2) {
			e2.printStackTrace();
		}

		Node[] links = visitor.getTags();
		for (int i = 0; i < links.length; i++) {
			LinkTag linkTag = (LinkTag) links[i];
			returnList.add(linkTag.getLink());

		}
		return returnList;

	}

	public void run() {
		while (true) {
			InfoPacket packet = null;
			try {
				packet = connection.receivePacket();
				
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
		
			//dla każdej strony wyszukuje linki
			InfoPacket retPacket=new InfoPacket(packet.getPage());
			retPacket.setUrlList(parseURL(packet.getPage()));

			
			//wyszukiwanie zdań do wykonania
			for(TaskType t:packet.getTaskList()){
				if(t==TaskType.keyword){
					Boolean retBool=new Boolean(findWord(packet.getPage(),(String)packet.getTaskArgument(t)));
					retPacket.addTask(t,retBool);
					
				}
			}
			
				connection.sendInfoPacket(retPacket);
			

		}
	}
}
